<?php
namespace Secret\Repositories;

use Secret\Common\Utils;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use ReflectionObject;

class ContentRepository extends \Doctrine\ORM\EntityRepository {

	public function data($model, $whereDql = '', $params = array(), $options = array()) {
		$page = isset($options['page']) ? $options['page'] : null;
		$limit = isset($options['limit']) ? $options['limit'] : null;
		$sort = isset($options['sort']) ? $options['sort'] : 'id';
		$order = isset($options['order']) ? $options['order'] : 'DESC';
		$model = $this->model($model);
		$columnsJson = $model['columnsJson'];
		usort($columnsJson, function ($a, $b) {
			return strlen($a['field']) < strlen($b['field']) ? 1 : - 1;
		});
		foreach ($columnsJson as $itm) {
			$whereDql = str_replace($itm['field'], $itm['mapping'], $whereDql);
		}
		foreach ($params as $idx => $itm) {
			foreach ($columnsJson as $itm2) {
				if ($idx == $itm2['field']) {
					unset($params[$idx]);
					$params[$itm2['mapping']] = $itm;
				}
			}
		}
		foreach ($columnsJson as $itm) {
			if ($sort == $itm['field']) {
				$sort = $itm['mapping'];
			}
		}
		$qb = $this->_em->createQueryBuilder()
			->from('Secret\Entities\Content', 'entity')
			->select('entity');
		if (! empty($whereDql)) {
			$qb->where($whereDql);
		}
		if (count($params) > 0) {
			$qb->setParameters($params);
		}
		$qb->andWhere('entity.modelId = ' . $model['id']);
		if ($page && $limit) {
			$qb->setFirstResult(($page - 1) * $limit);
			$qb->setMaxResults($limit);
		}
		if ($sort && $order) {
			if (strpos($sort, '.') === FALSE) {
				$qb->orderBy('entity.' . $sort, $order);
			} else {
				$qb->orderBy($sort, $order);
			}
		}
		$result = $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
		$model['_data'] = array();
		foreach ($result as $itm) {
			global $CMS_COLUMN_META;
			$row = array();
			foreach ($CMS_COLUMN_META as $itm2) {
				if (gettype($itm[$itm2]) == 'object') {
					$format = 'Y-m-d';
					$row[$itm2] = $itm[$itm2]->format($format);
				} else {
					$row[$itm2] = $itm[$itm2];
				}
			}
			foreach ($model['columnsJson'] as $itm2) {
				if (gettype($itm[$itm2['mapping']]) == 'object') {
					$format = ($itm2['type'] == 'date' || $itm2['type'] == 'datetime' || $itm2['type'] == 'time' || $itm2['type'] == 'birthday') ? 'Y-m-d' : 'Y-m-d H:i:s';
					$row[$itm2['field']] = $itm[$itm2['mapping']]->format($format);
				} else {
					$row[$itm2['field']] = $itm[$itm2['mapping']];
				}
			}
			ksort($row);
			$model['_data'][] = $row;
		}
		$qb = $this->_em->createQueryBuilder()
			->from('Secret\Entities\Content', 'entity')
			->select('COUNT(entity.id) AS total');
		if (! empty($whereDql)) {
			$qb->where($whereDql);
		}
		if (count($params) > 0) {
			$qb->setParameters($params);
		}
		$qb->andWhere('entity.modelId = ' . $model['id']);
		$result = $qb->getQuery()->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
		$model['_meta'] = array('page' => $page,'limit' => $limit,'sort' => $sort,'order' => $order,'total' => $result[0]['total']);
		return $model;
	}

	public function create($model) {
		$model = $this->model($model);
		$model['_data'] = array(array());
		$model['_data'][0]['id'] = null;
		foreach ($model['columnsJson'] as $itm) {
			$model['_data'][0][$itm['field']] = $itm['defaultValue'];
		}
		global $CMS_COLUMN_META;
		foreach ($CMS_COLUMN_META as $itm) {
			if ($itm == 'id') {
				continue;
			}
			$value = '';
			if ($itm == 'added' || $itm == 'lastModified') {
				$value = date('Y-m-d H:i:s');
			}
			if ($itm == 'modelId') {
				$value = $model['id'];
			}
			if ($itm == 'rank' || $itm == 'active') {
				$value = 0;
			}
			$model['_data'][0][$itm] = $value;
		}
		return $model;
	}

	public function save(&$model) {
		$contents = array();
		foreach ($model['_data'] as &$itm) {
			$content = new \Secret\Entities\Content();
			if (isset($itm['id']) && $itm['id'] != '') {
				$content = $this->_em->getRepository('Secret\Entities\Content')->find($itm['id']);
			}
			$reflectionObj = new ReflectionObject($content);
			foreach ($model['columnsJson'] as $itm2) {
				if (isset($itm[$itm2['field']])) {
					$value = $itm[$itm2['field']];
					if ($itm2['type']['name'] == 'choice' && isset($itm2['type']['options']['multiple']) && $itm2['type']['options']['multiple']) {
						if (!$value || $value == '') {
							$value = array();
						}
						$value = json_encode($value);
					} else if (strtolower($itm2['type']['name']) == 'password') {
						$encoder = new MessageDigestPasswordEncoder();
						$value = $encoder->encodePassword($value, '');
					}
					$reflectionMethod = $reflectionObj->getMethod('set' . ucfirst($itm2['mapping']));
					$reflectionMethod->invoke($content, $value);
				}
			}
			
			if (isset($itm[$model['idField']])) {
				$itm['slug'] = Utils::slugify($itm[$model['idField']]);
			}
			global $CMS_COLUMN_META;
			foreach ($CMS_COLUMN_META as $itm2) {
				if ($itm2 == 'id') {
					continue;
				}
				if (isset($itm[$itm2])) {
					$value = $itm[$itm2];
					if ($value && $itm2 == 'added') {
						continue;
					}
					if ($itm2 == 'added' || $itm2 == 'lastModified') {
						$value = new \Datetime($value);
					}
					$reflectionMethod = $reflectionObj->getMethod('set' . ucfirst($itm2));
					$reflectionMethod->invoke($content, $value);
				}
			}
			if (!$content->getId()) {
				$rank = 0;
				$result = $this->data($model['name'], '', array(), array('sort' => 'rank', 'order' => 'DESC', 'page' => 1, 'limit' => 1));
				if (count($result['_data']) > 0) {
					$rank = $result['_data'][0]['rank'] + 1;
				}
				$content->setRank($rank);
				$content->setParentId(0);
			}
// 			$content->setModelId($model['id']);
			$this->_em->persist($content);
			$contents[] = $content;
		}
		$this->_em->flush();
		foreach ($model['_data'] as $idx => &$itm) {
			$itm['id'] = $contents[$idx]->getId();
		}
		return $model;
	}

	public function model($model) {
		if (gettype($model) != 'string') {
			return $model;
		}
		// if(!isset($_SESSION[md5($model)])) {
		$models = $this->_em->createQueryBuilder()
			->from('Secret\Entities\Model', 'e')
			->select('e')
			->getQuery()
			->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
		foreach ($models as $itm) {
			$itm['columnsJson'] = json_decode($itm['columnsJson'], true);
			foreach ($itm['columnsJson'] as &$itm2) {
				$itm2 = (array) $itm2;
			}
			$_SESSION[md5($itm['name'])] = $itm;
		}
		// }
		return $_SESSION[md5($model)];
	}
}